package com.mvc.web.common.interceptor;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Enumeration;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.mvc.web.common.base.NotNeedCheckCookies;
import com.mvc.web.common.utils.AESUtil;
import com.mvc.web.common.utils.DomainUtils;
import com.mvc.web.common.utils.MailUtil;
import com.mvc.web.common.utils.ToolsUtils;

/**
 * @Description: 拦截器
 * @author 白海安 （baihaian@126.com） 2016年6月29日 下午2:53:49
 * @version V1.0
 */
public class CheckInterceptor extends HandlerInterceptorAdapter {

	protected Logger logger = Logger.getLogger(this.getClass().getName());

	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		//打印出客户端浏览器的内核
		String servletPath = request.getServletPath();
		if(ToolsUtils.isNotEmpty(servletPath)&&(servletPath.contains("svg"))){
			return super.preHandle(request, response, handler);
		}
		String requestid = request.getHeader("x_qmc_logid32");
		if (ToolsUtils.isEmpty(requestid)) {
			requestid = System.currentTimeMillis() + "";
		}

		String contextPath = request.getContextPath();
		request.setAttribute("uri", servletPath);
		//不需要验证cookie
		if (handler instanceof HandlerMethod) {
			HandlerMethod hm = (HandlerMethod) handler;
			NotNeedCheckCookies hasNotCheckAnno = hm.getMethod().getAnnotation(NotNeedCheckCookies.class);
			if (hasNotCheckAnno != null) {
				return super.preHandle(request, response, handler);
			}
		} else if(servletPath.startsWith("/api")){
			response.sendRedirect(contextPath + "/login/noMethod");
			return false;
		}else{
			return true;
		}
		// 验证cookie登录信息
		Cookie[] cookies = request.getCookies();
		if (cookies == null && servletPath.startsWith("/api")) {
			response.sendRedirect(contextPath + "/login/noCookie");
			return false;
		} else if (cookies == null) {
			pleaseLogin(response,contextPath);
			return false;
		}
		String uid = "";
		for (Cookie c : cookies) {
			if ("HYBBU".equals(c.getName())) {
				try {
					uid = AESUtil.base64AESDecrypt(c.getValue());
					logger.info("requestid："+requestid+" uid：" + uid);
				} catch (Exception e) {
					if (servletPath.startsWith("/api")) {
						response.sendRedirect(contextPath + "/login/noCookie");
						return false;
					} else {
						pleaseLogin(response, contextPath);
						return false;
					}
				}
			}
		}
		if ((ToolsUtils.isEmpty(uid))
				&& servletPath.startsWith("/api")) {
			response.sendRedirect(contextPath + "/login/noCookie");
			return false;
		} else if (ToolsUtils.isEmpty(uid)) {
			pleaseLogin(response, contextPath);
			return false;
		}
		return super.preHandle(request, response, handler);
	}

	private void pleaseLogin(HttpServletResponse response,String contextPath) {
		PrintWriter writer;
		try {
			writer = response.getWriter();
			response.setContentType("text/html;charset=UTF-8");
			writer.println("<script>");
			writer.println("alert('请登录系统');");
			writer.println("function wf(window){if(!window.opener){window.parent.location = '"
					+ contextPath
					+ "/';}else{window.parent.location = '"
					+ contextPath + "/';wf(window.opener);}}");
			writer.println("wf(window)");
			writer.println("</script>");
			writer.flush();
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/** 
	 * 这个方法只会在当前这个Interceptor的preHandle方法返回值为true的时候才会执行。postHandle是进行处理器拦截用的，它的执行时间是在处理器进行处理之 
	 * 后，也就是在Controller的方法调用之后执行，但是它会在DispatcherServlet进行视图的渲染之前执行，也就是说在这个方法中你可以对ModelAndView进行操 
	 * 作。这个方法的链式结构跟正常访问的方向是相反的，也就是说先声明的Interceptor拦截器该方法反而会后调用，这跟Struts2里面的拦截器的执行过程有点像， 
	 * 只是Struts2里面的intercept方法中要手动的调用ActionInvocation的invoke方法，Struts2中调用ActionInvocation的invoke方法就是调用下一个Interceptor 
	 * 或者是调用action，然后要在Interceptor之前调用的内容都写在调用invoke之前，要在Interceptor之后调用的内容都写在调用invoke方法之后。 
	*/ 
	@Override
	public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		if(modelAndView==null){
			super.postHandle(request, response, handler, modelAndView);
			return;
		}
		String local_url =request.getServletPath();
		//项目全局返回请求的
		modelAndView.addObject("local_url", local_url);
		super.postHandle(request, response, handler, modelAndView);
	}
	
	@Override
    public void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception e)
            throws Exception {
		if(e!=null){
			e.printStackTrace();
			StringWriter sw = new StringWriter();   
	        e.printStackTrace(new PrintWriter(sw, true));   
	        String tempContextUrl = DomainUtils.getDomain(request.getRequestURL()==null?"":request.getRequestURL().toString());
	        if(ToolsUtils.isNotEmpty(tempContextUrl)&&tempContextUrl.contains("com")){
	        	Enumeration<String> enu=request.getParameterNames();  
	        	String param = "params--> ";
	        	if(enu!=null){
	        		while(enu.hasMoreElements()){  
	        			String paraName=(String)enu.nextElement();  
	        			param+=paraName + ":"+request.getParameter(paraName)+"<br>";
	        		}
	        	}
	        	String local_url =request.getServletPath();
	        	String requestid = request.getHeader("X-Qmc-Logid32");
	        	String ctype = request.getHeader("ctype");
	        	if (ToolsUtils.isEmpty(requestid)) {
	        		requestid = System.currentTimeMillis() + "";
	        	}
	        	String str = " domain:"+tempContextUrl+" ctype:"+ctype+" requestId:"+requestid+" IP:"+ToolsUtils.getRealIP(request)+" API:"+local_url+"<br>";
	        	MailUtil mu = new MailUtil("货运巴巴异常", str+sw.toString()+"<br>"+param, "baihaian@126.com", null);
	        	mu.sendEmail();
        	}
		}
    }
}
